﻿using System;
using System.Linq;
using System.Linq.Expressions;
using DosTexPrj.Core.RepositoriesInterface;
using NHibernate;
using NHibernate.Linq;

namespace DosTexPrj.Implement.NHibernate.RepositoriesImp
{
    public class Repository : IRepository
    {
        protected readonly ISessionFactory _sessionFactory;

        public Repository(ISessionFactory sessionFactory)
        {
            this._sessionFactory = sessionFactory;
        }

        public TEntity FindByKey<TEntity>(object key) where TEntity : class
        {
            using (var uow = new UnitOfWork(this._sessionFactory))
            {
                return uow.Session.Get<TEntity>(key);
            }
        }

        public IQueryable<TEntity> GetAll<TEntity>() where TEntity : class
        {
            using (var uow = new UnitOfWork(this._sessionFactory))
            {
                return uow.Session.Query<TEntity>().ToList<TEntity>().AsQueryable();
            }
        }

        public IQueryable<TEntity> FindByCondition<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
        {
            using (var uow = new UnitOfWork(this._sessionFactory))
            {
                return uow.Session.Query<TEntity>().Where(predicate).ToList<TEntity>().AsQueryable();
            }
        }

        public TEntity Save<TEntity>(TEntity entity) where TEntity : class
        {
            using (var uow = new UnitOfWork(this._sessionFactory))
            {
                try
                {
                    uow.Session.SaveOrUpdate(entity);
                    uow.Commit();
                    return entity;
                }
                catch (Exception ex)
                {
                    uow.Rollback();
                    throw ex;
                }
            }
        }

        public void Delete<TEntity>(Expression<Func<TEntity, bool>> predicate) where TEntity : class
        {
            using (var uow = new UnitOfWork(this._sessionFactory))
            {
                try
                {
                    var filterResult = this.FindByCondition<TEntity>(predicate).ToList();
                    foreach (var item in filterResult)
                    {
                        uow.Session.Delete(item);
                    }
                    uow.Commit();
                }
                catch (Exception ex)
                {
                    uow.Rollback();
                    throw ex;
                }
            }
        }

        public void Dispose()
        {
        }
    }
}